package com.jic.market.impl;

import com.beust.jcommander.internal.Sets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jic.common.base.vo.AdminOperate;
import com.jic.common.base.vo.Page;
import com.jic.common.base.vo.PageResult;
import com.jic.common.base.vo.RestResult;
import com.jic.common.base.vo.enums.DeptTypeEnums;
import com.jic.common.utils.IDUtils;
import com.jic.market.common.base.MarketBaseService;
import com.jic.market.common.constant.PatchGrouponThemeConstant;
import com.jic.market.common.enums.DeleteFlagEnum;
import com.jic.market.common.enums.MerchantTypeEnum;
import com.jic.market.common.enums.MutexFlagEnum;
import com.jic.market.common.util.ListUtils;
import com.jic.market.common.util.LoginService;
import com.jic.market.entity.*;
import com.jic.market.entity.mutex.MutexModel;
import com.jic.market.entity.mutex.MutexProductEntity;
import com.jic.market.entity.mutex.MutexResultContext;
import com.jic.market.enums.FrontPromotionTypeEnum;
import com.jic.market.enums.PromotionProductTypeEnum;
import com.jic.market.enums.PromotionStatusEnum;
import com.jic.market.enums.PromotionTypeEnum;
import com.jic.market.exception.BussinessException;
import com.jic.market.mapper.PatchGrouponMerchantEntityMapper;
import com.jic.market.mapper.PatchGrouponMpEntityMapper;
import com.jic.market.mapper.PatchGrouponThemeEntityMapper;
import com.jic.market.mapper.PatchGrouponThemeMapper;
import com.jic.market.orm.Pagination;
import com.jic.market.request.*;
import com.jic.market.request.manager.patchgroup.PatchGroupIdListQueryRequest;
import com.jic.market.response.PageResponse;
import com.jic.market.response.PatchGroupProductV2Response;
import com.jic.market.response.PatchGrouponMerchantResponse;
import com.jic.market.response.PatchGrouponThemeResponse;
import com.jic.market.service.*;
import com.jic.market.service.mutex.MutexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 拼团活动表
 * @author : yinhaijun
 * @email :
 * @since : 2020-01-10 11:11:23
 * @version : v1.0.0
 */
@Service
@Slf4j
public class PatchGrouponThemeServiceImpl extends MarketBaseService implements PatchGrouponThemeService {
    private static ExecutorService executorServiceR = Executors.newFixedThreadPool(20);

    @Autowired
    private PatchGrouponThemeMapper patchGrouponThemeMapper;

    @Autowired
    private PatchGrouponThemeEntityMapper curMapper;

    @Autowired
    LoginService loginService;
    @Autowired
    private PatchGrouponLimitService patchGrouponLimitService;

    @Resource
    private PatchGrouponMpService patchGrouponMpService;

    @Resource
    private PatchGrouponMerchantService patchGrouponMerchantService;

    @Resource
    private PromotionTemplateService promotionTemplateService;

    @Autowired
    private PatchGrouponStockLmtService patchGrouponStockLmtService;

    @Autowired
    private PatchGrouponMerchantEntityMapper patchGrouponMerchantEntityMapper;

    @Autowired
    private PatchGroupMerchantProductService patchGroupMerchantProductService;

    @Autowired
    MutexService mutexService;

    @Autowired
    PromotionMutexService promotionMutexService;

    @Autowired
    private PatchGrouponMpEntityMapper patchGrouponMpEntityMapper;

    @Autowired
    private PromotionMemberGradeService promotionMemberGradeService;

    @Override
    public Long insert(PatchGrouponThemeRequest request) {
        PatchGrouponThemeEntity promotionEntity = new PatchGrouponThemeEntity();
        BeanUtils.copyProperties(request, promotionEntity);

        AdminOperate adminOperate = request.getAdminOperate();
        promotionEntity.setMemTypes(request.getMemTypes());
        promotionEntity.setFrontPromType(FrontPromotionTypeEnum.GROUPON.getCode());
        promotionEntity.setGroupCode(IDUtils.GenerateBillNo());
        /**
         * 设置拼团类型
         */
        promotionEntity.setPromType(PromotionTypeEnum.GROUPON.getCode());
        promotionEntity.setCreateTime(new Date());
        promotionEntity.setUpdateTime(new Date());
        promotionEntity.setCreatorName(adminOperate.getOperateName());
        promotionEntity.setCreator(adminOperate.getOperator());
        promotionEntity.setUpdatorName(adminOperate.getOperateName());
        promotionEntity.setUpdator(adminOperate.getOperator());
        promotionEntity.setDeptId(adminOperate.getDeptId());
        // 添加平台类型
        promotionEntity.setDeptType(adminOperate.getDeptType().getCode());
//        promotionEntity.setMerchantId(adminOperate.getMerchantIds());
//        promotionEntity.setStoreId(adminOperate.getStoreIds());
        // 设置为草稿状态
        promotionEntity.setStatus(PromotionStatusEnum.DRAFT.getCode());
        String fileUrl = prepareSetPatchGrouponFileUrl(request.getFileUrl());
        promotionEntity.setFileUrl(fileUrl);

        if (null != request.getChannelCodes() && !request.getChannelCodes().isEmpty()) {
            promotionEntity.setChannelCodes(request.getChannelCodes());
        }

        if (null != request.getProUserType() && !request.getProUserType().isEmpty()) {
            promotionEntity.setProUserType(Joiner.on("|").join(request.getProUserType()));
        }
        if (null != request.getProMemberType() && !request.getProMemberType().isEmpty()) {
            promotionEntity.setProMemberType(Joiner.on("|").join(request.getProMemberType()));
        }
        if (null != request.getProMemberLevel() && !request.getProMemberLevel().isEmpty()) {
            promotionEntity.setProMemberLevel(Joiner.on("|").join(request.getProMemberLevel()));
        }

        if (null != request.getCustomerLimit() && !request.getCustomerLimit().isEmpty()) {
            promotionEntity.setCustomerLimit(Joiner.on("|").join(request.getCustomerLimit()));
        }

        if (null != request.getOfferedCustomerLimit() && !request.getOfferedCustomerLimit().isEmpty()) {
            promotionEntity.setOfferedCustomerLimit(Joiner.on("|").join(request.getOfferedCustomerLimit()));
        }

        if (null != request.getStoreArea() && !request.getStoreArea().isEmpty()) {
            promotionEntity.setStoreArea(Joiner.on("|").join(request.getStoreArea()));
        }

        if (null != request.getUserArea() && !request.getUserArea().isEmpty()) {
            promotionEntity.setUserArea(Joiner.on("|").join(request.getUserArea()));
        }

        long flag = curMapper.insert(promotionEntity);

        MemberGradeInfoRequest memberGradeInfoRequest = new MemberGradeInfoRequest();
        memberGradeInfoRequest.setPromotionId(promotionEntity.getGroupCode());
        memberGradeInfoRequest.setPromotionCode(promotionEntity.getGroupCode());
        memberGradeInfoRequest.setPromType(promotionEntity.getPromType());
        memberGradeInfoRequest.setFrontPromType(promotionEntity.getFrontPromType());
        memberGradeInfoRequest.setPromotionMemberGradeList(request.getPromotionMemberGradeList());
        promotionMemberGradeService.addMemberGrade(memberGradeInfoRequest);

        if(flag >0){
            return promotionEntity.getId();
        }else {
            return null;
        }
    }

    /**
     * 准备设置活动图片地址的数据
     * @param fileUrl
     * @return
     */
    private String prepareSetPatchGrouponFileUrl(List<String> fileUrl) {
        String urlImages = "";
        if (CollectionUtils.isNotEmpty(fileUrl)) {
            for (String url : fileUrl) {
                if (!StringUtils.isEmpty(url)) {
                    urlImages = url + "," + urlImages;
                }
            }
        }
        return urlImages;
    }

    /**
     * 将图片地址转成为list
     * @param fileUrl
     * @return
     */
    private List<String> getPatchGrouponFileUrlList(String fileUrl) {
        List<String> imagesList = new ArrayList<>();
        if (!StringUtils.isEmpty(fileUrl)) {
            String[] str = fileUrl.split(",");
            imagesList = Arrays.stream(str).collect(Collectors.toList());
        }
        return imagesList;
    }

    @Override
    public long delete(Long id) {
        int delete = curMapper.delete(id);
        //删除商品
        patchGrouponMpEntityMapper.deleteEntityByPromotionId(id);
        //删除互斥
        promotionMutexService.deleteByPromotionIdAndPromType(id, PromotionTypeEnum.GROUPON.getCode());
        return delete;
    }

    @Override
    public long update(PatchGrouponTheme patchGrouponTheme) {
        patchGrouponTheme.setUpdateTime(new Date());
        return patchGrouponThemeMapper.update(patchGrouponTheme);
    }

    @Override
    public PatchGrouponThemeEntity queryById(Long id){
        return curMapper.queryById(id);
    }

    @Override
    public List<PatchGrouponTheme> query(PatchGrouponTheme patchGrouponTheme){
        return patchGrouponThemeMapper.query(patchGrouponTheme);
    }

    @Override
    public PageResult<PatchGrouponTheme> queryPage(PatchGrouponTheme patchGrouponTheme, Page pageQuery) {
        //计算下标
        int startIndex = (pageQuery.getStart() - 1) * pageQuery.getLimit();
        List<PatchGrouponTheme> list = patchGrouponThemeMapper.queryPage(startIndex, pageQuery.getLimit(), patchGrouponTheme);
        long count = patchGrouponThemeMapper.queryPageCount(patchGrouponTheme);
        PageResult pageResult = new PageResult();
        pageResult.setRows(list);
        pageResult.setTotal(count);
        return pageResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long save(PatchGrouponThemeRequest request) {
        Long id =this.insert(request);
        patchGrouponLimitService.addLimitByUser(id, request);
        return id;
    }

    @Override
    public PageResponse<PatchGrouponThemeResponse> queryPage2(PatchGrouponThemeRequest request) {
        Pagination pagination = Pagination.build(request);

        PatchGrouponThemeEntity paramEntity = new PatchGrouponThemeEntity();
        BeanUtils.copyProperties(request, paramEntity);
        // 按创建人搜索
        paramEntity.setCreatorName(request.getCreatorNameForSearch());
//        paramEntity.setDeptId(request.getAdminOperate().getDeptId());
        paramEntity.setDeptType(request.getAdminOperate().getDeptType().getCode());
//        Set<Long> promotionIds = getPromotionIdsByDeptType(request);
//        paramEntity.setIds(promotionIds);

        // TODO
        //        if(promotionIds == null){
//            return new PageResponse<PromotionResponse>()
//                    .setPageNo(request.getPageNo())
//                    .setPageSize(request.getPageSize())
//                    .setTotalCount(0);
//        }

        List<PatchGrouponThemeEntity> entityList = curMapper.findOfPageByDept(paramEntity, pagination);
        int count = curMapper.countOfPageByDept(paramEntity);
        PageResponse<PatchGrouponThemeResponse> responsePageResponse = new PageResponse<PatchGrouponThemeResponse>()
                .setPageNo(request.getPageNo())
                .setPageSize(request.getPageSize())
                .setTotalCount(count)
                .setList(Optional.ofNullable(entityList).orElse(Lists.newArrayList()).stream().map(e -> {
                    PatchGrouponThemeResponse response = new PatchGrouponThemeResponse();
                    BeanUtils.copyProperties(e, response);
                    response.setEditFlag(Long.valueOf(response.getDeptId()).equals(request.getAdminOperate().getDeptId()) ? true : false);
                    return response;
                }).collect(Collectors.toList()));

        return responsePageResponse;
    }



    /**
     * 根据deptType获取promotiondids,bizId(运营id,子平台id，或者merchantid,storeId)
     * @param request
     * @return
     */
    private Set<Long> getPromotionIdsByDeptType(PatchGrouponThemeRequest request) {
        Set<Long> promotionIds = new HashSet<>();
        DeptTypeEnums deptType = request.getDeptType();
        List<PatchGrouponMerchantEntity> merchantAll = null;
        List<PatchGrouponMerchantEntity> storeAll = null;
        List<Long> merchantIds = null;
        List<Long> storeIds = null;
        if(deptType != null){
            Long bizId = request.getBusinessId();
            //母平台
            if(deptType.equals(DeptTypeEnums.OPERATION_PLATFORM) || deptType.equals(DeptTypeEnums.CHILD_PLATFORM)){
                merchantIds = request.getMerchantIds();
                storeIds = request.getStoreIds();
            }else if(deptType.equals(DeptTypeEnums.MERCHANT_PLATFORM)){
                merchantIds = Arrays.asList(bizId);
                storeIds = request.getStoreIds();
            }else if(deptType.equals(DeptTypeEnums.STORE_PLATFORM)){
                storeIds = Arrays.asList(bizId);
            }
        }
        if(CollectionUtils.isNotEmpty(merchantIds)){
            merchantAll = patchGrouponMerchantEntityMapper.findAllByMerchantIds(merchantIds);
            merchantAll.forEach(x->{
                promotionIds.add(x.getPromotionId());
            });
        }
        if(CollectionUtils.isNotEmpty(storeIds)){
            storeAll = patchGrouponMerchantEntityMapper.findAllByStoreIds(storeIds);
            storeAll.forEach(x->{
                promotionIds.add(x.getPromotionId());
            });
        }
        return CollectionUtils.isEmpty(promotionIds) ? null : promotionIds;
    }


    @Override
    public Long copy(Long id) {
        PatchGrouponThemeEntity byId = curMapper.getById(id);

        byId.setId(null);
        byId.setPromName(byId.getPromName() + "-复制");
        byId.setCreateTime(new Date());
        byId.setStatus(PatchGrouponThemeConstant.StatusEnum.STATUS_05.getCode());
        curMapper.insert(byId);

        return byId.getId();
    }

    @Override
    public RestResult<Long> copy(PatchGrouponThemeCopyRequest request) {
        return executeQuery(() -> {
            // 复制主表
            PatchGrouponThemeEntity promotionEntityQ = new PatchGrouponThemeEntity();
            promotionEntityQ.setGroupCode(request.getPromotionId());
            PatchGrouponThemeEntity promotionEntity = curMapper.query(promotionEntityQ);
            // 复制配置信息，返回新的活动id
            PromotionTemplateService.CopyResult copyResult = copyConfig(request.getPromotionId(), PromotionStatusEnum.DRAFT, promotionEntity.getPromName() + "-复制");
            copyResult.setAdminOperate(request.getAdminOperate());
            if(null != copyResult){
                return copyResult.getId();
            }
            return null;
        });
    }

    @Override
    public RestResult<Long> saveTemplate(PatchGrouponThemeCopyRequest request) {
        //判断名字是否重复
        PatchGrouponThemeEntity patchGrouponThemeEntity = new PatchGrouponThemeEntity();
        patchGrouponThemeEntity.setPromName(request.getTemplateName());
        int count = curMapper.countOfTemplate(patchGrouponThemeEntity);
        if(count > 0){
            throw new BussinessException("-1", "模板名称重复");
        }

        return executeQuery(() -> {
            Long templateId = promotionTemplateService.saveTemplate(() -> {
                // 复制配置信息
                PromotionTemplateService.CopyResult copyResult = copyConfig(request.getPromotionId(), PromotionStatusEnum.TEMPLATE, request.getTemplateName());
                copyResult.setAdminOperate(request.getAdminOperate());
                return copyResult;
            });
            return templateId;
        });
    }

    @Override
    public Integer updateById(PatchGrouponThemeRequest request) {
        PatchGrouponThemeEntity promotionEntity = new PatchGrouponThemeEntity();
        BeanUtils.copyProperties(request, promotionEntity);

        String fileUrl = prepareSetPatchGrouponFileUrl(request.getFileUrl());
        promotionEntity.setFileUrl(fileUrl);

        if (null != request.getChannelCodes() && !request.getChannelCodes().isEmpty()) {
            // 前端是 Tree 树形控件 channelCodes: "179,9,10"
            promotionEntity.setChannelCodes(request.getChannelCodes());
        }

        if (null != request.getProUserType() && !request.getProUserType().isEmpty()) {
            promotionEntity.setProUserType(Joiner.on("|").join(request.getProUserType()));
        }
        if (null != request.getProMemberType() && !request.getProMemberType().isEmpty()) {
            promotionEntity.setProMemberType(Joiner.on("|").join(request.getProMemberType()));
        }
        if (null != request.getProMemberLevel() && !request.getProMemberLevel().isEmpty()) {
            promotionEntity.setProMemberLevel(Joiner.on("|").join(request.getProMemberLevel()));
        }

        if (null != request.getCustomerLimit() && !request.getCustomerLimit().isEmpty()) {
            promotionEntity.setCustomerLimit(Joiner.on("|").join(request.getCustomerLimit()));
        }

        if (null != request.getOfferedCustomerLimit() && !request.getOfferedCustomerLimit().isEmpty()) {
            promotionEntity.setOfferedCustomerLimit(Joiner.on("|").join(request.getOfferedCustomerLimit()));
        }

        if (null != request.getStoreArea() && !request.getStoreArea().isEmpty()) {
            promotionEntity.setStoreArea(Joiner.on("|").join(request.getStoreArea()));
        }

        if (null != request.getUserArea() && !request.getUserArea().isEmpty()) {
            promotionEntity.setUserArea(Joiner.on("|").join(request.getUserArea()));
        }

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                updatePromotionMutex(promotionEntity,request);
            }
        });
        t.start();

        int flag = curMapper.update(promotionEntity);


        MemberGradeInfoRequest memberGradeInfoRequest = new MemberGradeInfoRequest();
        memberGradeInfoRequest.setPromotionId(promotionEntity.getGroupCode());
        memberGradeInfoRequest.setPromotionCode(promotionEntity.getGroupCode());
        memberGradeInfoRequest.setPromType(FrontPromotionTypeEnum.GROUPON.getPromType().getCode());
        memberGradeInfoRequest.setFrontPromType(FrontPromotionTypeEnum.GROUPON.getCode());
        memberGradeInfoRequest.setPromotionMemberGradeList(request.getPromotionMemberGradeList());
        promotionMemberGradeService.updateMemberGrade(memberGradeInfoRequest);

        return flag;

    }



    /**
     * 编辑时重新进行互斥校验
     * @param promotionEntity
     * @param request
     */
    private void updatePromotionMutex(PatchGrouponThemeEntity promotionEntity, PatchGrouponThemeRequest request){
        PatchGrouponMpEntity patchGrouponMpEntity = new PatchGrouponMpEntity();
        patchGrouponMpEntity.setPromotionId(request.getId());
        patchGrouponMpEntity.setDeleteFlag(0);
        patchGrouponMpEntity.setMutexFlag(0);
        patchGrouponMpEntity.setTypeOfProduct(PromotionProductTypeEnum.TYPE_SKU.getType());
        List<PatchGrouponMpEntity> merchantProductEntities = patchGrouponMpEntityMapper.findAll(patchGrouponMpEntity);
        List<Long> productIds = merchantProductEntities.stream().map(PatchGrouponMpEntity::getMpId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(productIds)){
            final Set<Long> mutexList = Sets.newHashSet();
            MutexResultContext mutexResultContext = mutexService.doProcessMutexByPatch(promotionEntity.getId(), productIds);
            mutexList.addAll(mutexResultContext.getMutexList());
            final Map<Long, Long> mutexMpIdMap = Maps.newHashMap();
            //变更互斥FLAG
            merchantProductEntities.forEach(x->{
                x.setMutexFlag(mutexList.contains(x.getMpId()) ? MutexFlagEnum.MUTEX.getCode() : MutexFlagEnum.UN_MUTEX.getCode());
                x.setUpdateTime(new Date());
                x.setUpdator(request.getAdminOperate().getOperator());
                if(mutexList.contains(x.getMpId())){
                    mutexMpIdMap.put(x.getMpId(), x.getId());
                }
                x.setUpdatorName(request.getAdminOperate().getOperateName());
                patchGrouponMpEntityMapper.update(x);
            });

            mutexResultContext.getMutexPromotionProducts().entrySet().forEach(e->{
                Set<MutexProductEntity> mutexProductEntitySet = e.getValue();
                promotionMutexService.deleteByPromotionProductId(mutexMpIdMap.get(e.getKey()));
                mutexProductEntitySet.forEach(m->{
                    promotionMutexService.insert(
                            new PromotionMutex()
                                    .setPromotionId(m.getPromotionId())
                                    .setPromType(m.getPromType())
                                    .setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode())
                                    .setPromotionMerchantProductId(mutexMpIdMap.get(e.getKey()))
                                    .setCreator(request.getAdminOperate().getOperator())
                                    .setCreatorName(request.getAdminOperate().getOperateName())
                    );
                });
            });
        }
    }

    @Override
    public PatchGrouponThemeResponse getById(Long id) {
        PatchGrouponThemeEntity byId = curMapper.getById(id);
        if (null == byId) {
            return null;
        }

        PatchGrouponThemeResponse response = new PatchGrouponThemeResponse();
        BeanUtils.copyProperties(byId, response);

        String channelCodesStr = byId.getChannelCodes();
        List<String> channelCodes =Arrays.asList(channelCodesStr.split(","));
        response.setChannelCodes(channelCodes);

        List<String> fileUrlList = getPatchGrouponFileUrlList(byId.getFileUrl());
        response.setFileUrl(fileUrlList);
        return response;
    }

    @Override
    public PatchGrouponThemeResponse getByPromotionCode(String groupCode) {
        PatchGrouponThemeEntity condition =new PatchGrouponThemeEntity();
        condition.setGroupCode(groupCode);
        PatchGrouponThemeEntity byId = curMapper.query(condition);
        if (null == byId) {
            return null;
        }

        PatchGrouponThemeResponse response = new PatchGrouponThemeResponse();
        BeanUtils.copyProperties(byId, response);

        String channelCodesStr = byId.getChannelCodes();
        List<String> channelCodes =Arrays.asList(channelCodesStr.split(","));
        response.setChannelCodes(channelCodes);

        List<String> fileUrlList = getPatchGrouponFileUrlList(byId.getFileUrl());
        response.setFileUrl(fileUrlList);
        return response;
    }

    @Override
    public PatchGrouponThemeResponse getPatchGrouponThemeByIdAndAdminOperate(PatchGrouponThemeRequest bo) {
        PatchGrouponThemeEntity byId = null;
        if(!StringUtils.isEmpty(bo.getGroupCode())){
            // 先查询出主键id
            PatchGrouponThemeEntity patchGrouponThemeEntityQ = new PatchGrouponThemeEntity();
            patchGrouponThemeEntityQ.setGroupCode(bo.getGroupCode());
            byId = curMapper.query(patchGrouponThemeEntityQ);
        }else if(null != bo.getId()) {
            byId = curMapper.getById(bo.getId());
        }else {
            // id和groupCode都为null的时候不能查询
            return null;
        }
        if (null == byId) {
            return null;
        }

        PatchGrouponThemeResponse response = new PatchGrouponThemeResponse();
        BeanUtils.copyProperties(byId, response);

//        String channelCodesStr = byId.getChannelCodes();
//        List<String> channelCodes =Arrays.asList(channelCodesStr.split(","));
//        response.setChannelCodes(channelCodes);

        List<String> fileUrlList = getPatchGrouponFileUrlList(byId.getFileUrl());
        response.setFileUrl(fileUrlList);

        response.setEditFlag(Long.valueOf(response.getDeptId()).equals(bo.getAdminOperate().getDeptId()) ? true : false);

//        List<PromotionMemberGradeRequest> promotionMemberGradeRequestList = promotionMemberGradeService.queryMemberGrade(byId.getGroupCode());
//        response.setPromotionMemberGradeList(promotionMemberGradeRequestList);
        return response;
    }

    /**
     * 复制方法
     * @param oldPromotionId 被复制的活动id
     * @param status 复制需要存储的状态
     * @param templateName 模板名
     * @return
     */
    private PromotionTemplateService.CopyResult copyConfig(String oldPromotionId, PromotionStatusEnum status, String templateName) {
        List<CompletableFuture<Integer>> completableFutures = new ArrayList<>();
        // 复制主表
        PatchGrouponThemeEntity promotionEntityQ = new PatchGrouponThemeEntity();
        promotionEntityQ.setGroupCode(oldPromotionId);
        PatchGrouponThemeEntity promotionEntity = curMapper.query(promotionEntityQ);

        String oldGroupCode = promotionEntity.getGroupCode();
        Long oldId = promotionEntity.getId();

        if(null == promotionEntity) {
            return null;
        }
        promotionEntity.setId(null);
        promotionEntity.setStatus(status.getCode());
//        promotionEntity.setStatus(PromotionStatusEnum.DRAFT.getCode());
        promotionEntity.setPromName(templateName);
        promotionEntity.setPromType(PromotionTypeEnum.GROUPON.getCode());
        promotionEntity.setFrontPromType(FrontPromotionTypeEnum.GROUPON.getCode());
        promotionEntity.setGroupCode(IDUtils.GenerateBillNo());
        promotionEntity.setCreateTime(new Date());
        promotionEntity.setUpdateTime(new Date());
        int flag = curMapper.insert(promotionEntity);
        if(0 == flag) {
            return null;
        }
        //结果组装
        PromotionTemplateService.CopyResult copyResult = new PromotionTemplateService.CopyResult();
        copyResult.setId(promotionEntity.getId());
        copyResult.setPromotionId(promotionEntity.getGroupCode());
        copyResult.setPromType(PromotionTypeEnum.getByCode(PromotionTypeEnum.GROUPON.getCode()));
        copyResult.setTemplateName(promotionEntity.getPromName());


        // 复制商家店铺表
        CompletableFuture<Integer> merchantCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                long start = System.currentTimeMillis();
                PatchGrouponMerchantEntity merchantEntityQ =new PatchGrouponMerchantEntity();
                merchantEntityQ.setPromotionId(oldId);
                merchantEntityQ.setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode());
                List<PatchGrouponMerchantEntity> patchGrouponMerchantEntityList = patchGrouponMerchantService.findAll(merchantEntityQ);
                if(null != patchGrouponMerchantEntityList && !patchGrouponMerchantEntityList.isEmpty()){
                    for(PatchGrouponMerchantEntity merchantEntity: patchGrouponMerchantEntityList){
                        merchantEntity.setId(null);
                        merchantEntity.setPromotionId(promotionEntity.getId());
                        merchantEntity.setCreateTime(new Date());
                        merchantEntity.setUpdateTime(new Date());
                        //patchGrouponMerchantService.insert(merchantEntity);
                    }
                    patchGrouponMerchantService.insertBatch(patchGrouponMerchantEntityList);
                }
                log.info("copyPatchConfig success promotionMerchant cost = {}", System.currentTimeMillis() - start);
            } catch (Exception e) {
                log.error("copyPatchConfig promotionMerchant error", e);
            }
            return 1;
        }, executorServiceR);
        completableFutures.add(merchantCompletableFuture);


        // 复制商家店铺表
        CompletableFuture<Integer> merchantProductCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                long start = System.currentTimeMillis();
                // 复制商品表
                PatchGrouponMp promotionProductQ =new PatchGrouponMp();
                promotionProductQ.setPromotionId(oldId);
                promotionProductQ.setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode());
                List<PatchGrouponMp> patchGrouponMpList = patchGrouponMpService.query(promotionProductQ);
                List<Long> productIds = patchGrouponMpList.stream().filter(x->{return x.getTypeOfProduct().equals(PromotionProductTypeEnum.TYPE_SKU.getType());}).map(PatchGrouponMp::getMpId).collect(Collectors.toList());
                if(null != patchGrouponMpList && !patchGrouponMpList.isEmpty()){
                    final Set<Long> mutexList = Sets.newHashSet();
                    final Map<Long, Long> mutexMpIdMap = Maps.newHashMap();
                    Map<Long, Set<MutexProductEntity>> mutexPromotionProducts = null;
                    if(status.equals(PromotionStatusEnum.DRAFT)){
                        MutexResultContext mutexResultContext = mutexService.doProcessMutex(
                                new MutexModel()
                                        .setPromotionId(promotionEntity.getId())
                                        .setPromType(promotionEntity.getPromType())
                                        .setFrontPromotionType(promotionEntity.getFrontPromType())
                                        .setProductList(productIds)
                        );
                        mutexList.addAll(mutexResultContext.getMutexList());
                        mutexPromotionProducts = mutexResultContext.getMutexPromotionProducts();

                    }

                    patchGrouponMpList.forEach(patchGrouponMp->{
                        patchGrouponMp.setId(null);
                        patchGrouponMp.setMutexFlag(mutexList.contains(patchGrouponMp.getMpId()) ? MutexFlagEnum.MUTEX.getCode() : MutexFlagEnum.UN_MUTEX.getCode());
                        patchGrouponMp.setPromotionId(promotionEntity.getId());
                        patchGrouponMp.setCreateTime(new Date());
                        patchGrouponMp.setUpdateTime(new Date());
                        patchGrouponMpService.insert(patchGrouponMp);
                        if(mutexList.contains(patchGrouponMp.getMpId())){
                            mutexMpIdMap.put(patchGrouponMp.getMpId(), patchGrouponMp.getId());
                        }
                    });
                    patchGrouponMpService.insertBatch(patchGrouponMpList);
                    Map<Long, Long> mpIdMap = Maps.newHashMap();
                    patchGrouponMpList.forEach(x->{
                        mpIdMap.put(x.getMpId(), x.getId());
                    });

                    // 复制限制表
                    PatchGrouponStockLmtEntity patchGrouponStockLmtQ =new PatchGrouponStockLmtEntity();
                    patchGrouponStockLmtQ.setRefPatchGrouponTheme(oldId);
//                    patchGrouponStockLmtQ.setMerchantProductId(patchGrouponMp.getMpId());
//                    patchGrouponStockLmtQ.setTypeOfProduct(patchGrouponMp.getTypeOfProduct());
                    patchGrouponStockLmtQ.setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode());
                    List<PatchGrouponStockLmtEntity> patchGrouponStockLmtList = patchGrouponStockLmtService.findAll(patchGrouponStockLmtQ);
                    if(null != patchGrouponStockLmtList && !patchGrouponStockLmtList.isEmpty()){
                        for(PatchGrouponStockLmtEntity patchGrouponStockLmtEntity : patchGrouponStockLmtList){
                            patchGrouponStockLmtEntity.setId(null);
                            patchGrouponStockLmtEntity.setRefPatchGrouponTheme(promotionEntity.getId());
                            patchGrouponStockLmtEntity.setPatchGrouponMpId(mpIdMap.get(patchGrouponStockLmtEntity.getMerchantProductId()));
                            patchGrouponStockLmtEntity.setCreateTime(new Date());
                            patchGrouponStockLmtEntity.setUpdateTime(new Date());
                            //patchGrouponStockLmtService.addPromotionLimitRule(patchGrouponStockLmtEntity);
                        }
                        patchGrouponStockLmtService.insertBatch(patchGrouponStockLmtList);
                    }


//                    for(PatchGrouponMp patchGrouponMp : patchGrouponMpList){
//                        patchGrouponMp.setId(null);
//                        patchGrouponMp.setMutexFlag(mutexList.contains(patchGrouponMp.getMpId()) ? MutexFlagEnum.MUTEX.getCode() : MutexFlagEnum.UN_MUTEX.getCode());
//                        patchGrouponMp.setPromotionId(promotionEntity.getId());
//                        patchGrouponMp.setCreateTime(new Date());
//                        patchGrouponMp.setUpdateTime(new Date());
//                        patchGrouponMpService.insert(patchGrouponMp);
//                        if(mutexList.contains(patchGrouponMp.getMpId())){
//                            mutexMpIdMap.put(patchGrouponMp.getMpId(), patchGrouponMp.getId());
//                        }
//
//                        // 复制限制表
//                        PatchGrouponStockLmtEntity patchGrouponStockLmtQ =new PatchGrouponStockLmtEntity();
//                        patchGrouponStockLmtQ.setRefPatchGrouponTheme(oldId);
//                        patchGrouponStockLmtQ.setMerchantProductId(patchGrouponMp.getMpId());
//                        patchGrouponStockLmtQ.setTypeOfProduct(patchGrouponMp.getTypeOfProduct());
//                        patchGrouponStockLmtQ.setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode());
//                        List<PatchGrouponStockLmtEntity> patchGrouponStockLmtList = patchGrouponStockLmtService.findAll(patchGrouponStockLmtQ);
//                        if(null != patchGrouponStockLmtList && !patchGrouponStockLmtList.isEmpty()){
//                            for(PatchGrouponStockLmtEntity patchGrouponStockLmtEntity : patchGrouponStockLmtList){
//                                patchGrouponStockLmtEntity.setId(null);
//                                patchGrouponStockLmtEntity.setRefPatchGrouponTheme(promotionEntity.getId());
//                                patchGrouponStockLmtEntity.setPatchGrouponMpId(patchGrouponMp.getId());
//                                patchGrouponStockLmtEntity.setCreateTime(new Date());
//                                patchGrouponStockLmtEntity.setUpdateTime(new Date());
//                                patchGrouponStockLmtService.addPromotionLimitRule(patchGrouponStockLmtEntity);
//                            }
//                        }
//                    }

                    if(mutexPromotionProducts != null){
                        mutexPromotionProducts.entrySet().forEach(e->{
                            Set<MutexProductEntity> mutexProductEntitySet = e.getValue();
                            promotionMutexService.deleteByPromotionProductId(mutexMpIdMap.get(e.getKey()));
                            List<PromotionMutex> collect = mutexProductEntitySet.stream().map(m -> {
                                return new PromotionMutex()
                                        .setPromotionId(m.getPromotionId())
                                        .setPromType(m.getPromType())
                                        .setDeleteFlag(DeleteFlagEnum.UN_DELETE.getCode())
                                        .setPromotionMerchantProductId(mutexMpIdMap.get(e.getKey()));
                            }).collect(Collectors.toList());
                            promotionMutexService.insertBatch(collect);
                        });
                    }
                }
                log.info("copyPatchConfig success merchantProduct cost = {}", System.currentTimeMillis() - start);
            } catch (Exception e) {
                log.error("copyPatchConfig merchantProduct error", e);
            }
            return 1;
        }, executorServiceR);
        completableFutures.add(merchantProductCompletableFuture);


        CompletableFuture<Integer> memberCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                long start = System.currentTimeMillis();
                promotionMemberGradeService.copyMemberGrade(oldGroupCode, promotionEntity.getGroupCode(), promotionEntity.getGroupCode());
                log.info("copyPatchConfig success mermber cost = {}", System.currentTimeMillis() - start);
            } catch (Exception e) {
                log.error("copyPatchConfig mermber error", e);
            }
            return 1;
        }, executorServiceR);
        completableFutures.add(memberCompletableFuture);
        CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();

        return copyResult;
    }

    @Override
    public List<PatchGrouponThemeResponse> queryListByIds(PatchGroupIdListQueryRequest request) {
        List<Long> ids = request.getIds();
        if (ids == null || ids.size() ==0){
            return null;
        }
        AdminOperate adminOperate = request.getAdminOperate();
        Long deptId = adminOperate.getDeptId();
        List<PatchGrouponTheme> patchGrouponThemes =
                curMapper.queryListByIds(deptId, DeleteFlagEnum.UN_DELETE.getCode(), ids);
        List<PatchGrouponThemeResponse> list =
                ListUtils.entityListToModelList(patchGrouponThemes,PatchGrouponThemeResponse.class);
        return list;
    }

    @Override
    public RestResult<Long> doUpdateStatus(ToUpdateStatusRequest req) {
        PatchGrouponTheme theme = new PatchGrouponTheme();
        theme.setId(req.getPromotionId());
        theme.setStatus(req.getStatus());

        // 如果状态是 待审核 则需要有商家，店铺，商品判断
        if(PromotionStatusEnum.TO_AUDIT.getCode().equals(req.getStatus())){
            RestResult restResult = this.reviewPromotion(req);
            if(restResult.getCode().equals("9999")){
                return restResult;
            }
        }
        Long count =this.update(theme);
        return RestResult.success(count);
    }

    @Override
    public RestResult reviewPromotion(ToUpdateStatusRequest request) {

        // 查询商家
//        Integer merchantTotal = getMerchantCount(request);

        // 查询店铺
//        Integer storeTotal = getStoreCount(request);

        // 查询商品
        Integer productTotal = getProductCount(request);

//        if( merchantTotal<=0|| storeTotal<=0 || productTotal<=0){
//            return RestResult.error("9999","商家、店铺、商品信息不全，无法提交审核");
//        }
        if( productTotal<=0){
            return RestResult.error("9999","商品信息不全，无法提交审核");
        }

        return RestResult.success("商家、店铺、商品信息完整");
    }

    private Integer getProductCount(ToUpdateStatusRequest request) {
        Integer productTotal = 0;
        PatchGroupPromotionProductQueryListV2Request productRequest =new PatchGroupPromotionProductQueryListV2Request();
        productRequest.setPromotionId(request.getPromotionId());
        productRequest.setStart(1);
        productRequest.setLimit(10);
        productRequest.setAdminOperate(request.getAdminOperate());

        PageResult<PatchGroupProductV2Response> productPageResp =patchGroupMerchantProductService.getPromotionProductListV2(productRequest);
        if(productPageResp ==null){
            productTotal = 0;
        }else {
            productTotal = new Long(productPageResp.getTotal()).intValue();
        }

        return productTotal;
    }

    private Integer getStoreCount(ToUpdateStatusRequest request) {
        Integer storeTotal = 0;
        PatchGrouponMerchantRequest storeRequest =new PatchGrouponMerchantRequest();
        storeRequest.setPromotionId(request.getPromotionId());
        storeRequest.setMerchantType(MerchantTypeEnum.STORE.getCode());
        storeRequest.setStart(1);
        storeRequest.setLimit(10);
        storeRequest.setAdminOperate(request.getAdminOperate());

        PageResponse<PatchGrouponMerchantResponse> storePageResp = patchGrouponMerchantService.listByPage(storeRequest);
        if(storePageResp ==null){
            storeTotal = 0;
        }else {
            storeTotal = storePageResp.getTotalCount();
        }

        return storeTotal;
    }

    private Integer getMerchantCount(ToUpdateStatusRequest request) {
        Integer merchantTotal = 0;
        PatchGrouponMerchantRequest merchantRequest =new PatchGrouponMerchantRequest();
        merchantRequest.setPromotionId(request.getPromotionId());
        merchantRequest.setMerchantType(MerchantTypeEnum.MERCHANT.getCode());
        merchantRequest.setStart(1);
        merchantRequest.setLimit(10);
        merchantRequest.setAdminOperate(request.getAdminOperate());

        PageResponse<PatchGrouponMerchantResponse> merchantPageResp = patchGrouponMerchantService.listByPage(merchantRequest);
        if(merchantPageResp ==null){
            merchantTotal = 0;
        }else {
            merchantTotal = merchantPageResp.getTotalCount();
        }
        return merchantTotal;
    }
}
